﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Collections;
using Reborn_Server.App1AppHandler;
using System.Xml;
using System.IO;
using System.Net.Sockets;
using Reborn_WorldServer;
using Reborn_WorldServer.App1AppHandler;

namespace App1AppHandler
{
    public class BagManager
    {
        List<BagPage> bagPages = new List<BagPage>();
        private Character MyCharacter;

        public BagManager(Character character)
        {
            MyCharacter = character;

            //LOAD ITEM IDs
            SqlConnection MyCon = new SqlConnection(Managers.DBConnectionString);
            SqlCommand SQLCom = new SqlCommand("Characters_Bags_Select", MyCon);
            SQLCom.CommandType = System.Data.CommandType.StoredProcedure;
            SQLCom.Parameters.AddWithValue("@CharacterID", character.ID);

            MyCon.Open();
            SqlDataReader SDR = SQLCom.ExecuteReader();

            while (SDR.Read())
            {
                BagPage bagPage = new BagPage();
                bagPage.PageNumber = int.Parse(SDR["PageNumber"].ToString());

                //WALK THROUGH COLUMNS
                for (int x = 0; x < 28; x++)
                {
                    if (SDR["Item" + x.ToString()] != DBNull.Value)
                    {
                        int boundTo = -1;
                        if (SDR["Item" + x.ToString() + "_BoundTo"] != DBNull.Value)
                            boundTo = int.Parse(SDR["Item" + x.ToString() + "_BoundTo"].ToString());

                        bagPage.bagItems[x] = Managers.GameHandler.CreateItem(int.Parse(SDR["Item" + x.ToString()].ToString()), boundTo);
                    }
                }

                bagPages.Add(bagPage);
            }

            SDR.Close();
            SDR.Dispose();

            MyCon.Close();
            MyCon.Dispose();

            UpdateBag();
        }

        public void SaveBag()
        {
            SqlConnection MyCon = new SqlConnection(Managers.DBConnectionString);
            MyCon.Open();
            SqlTransaction MyTrans = MyCon.BeginTransaction();

            SqlCommand SQLCom = new SqlCommand();
            SQLCom.CommandType = System.Data.CommandType.StoredProcedure;
            SQLCom.Connection = MyCon;
            SQLCom.Transaction = MyTrans;

            lock (bagPages)
            {
                try
                {
                    SQLCom.CommandText = "Characters_Bags_Update";
                    foreach (BagPage bp in bagPages)
                    {
                        SQLCom.Parameters.Clear();
                        SQLCom.Parameters.AddWithValue("@CharacterID", MyCharacter.ID);
                        SQLCom.Parameters.AddWithValue("@PageNumber", bp.PageNumber);

                        for (int x = 0; x < bp.bagItems.Length; x++)
                        {
                            if (bp.bagItems[x] != null && bp.bagItems[x].ID != -1)
                            {
                                SQLCom.Parameters.AddWithValue("@Item" + x.ToString(), bp.bagItems[x].ID);
                                SQLCom.Parameters.AddWithValue("@Item" + x.ToString() + "_BoundTo", bp.bagItems[x].BoundTo);
                            }
                        }

                        SQLCom.ExecuteNonQuery();
                    }
                    MyTrans.Commit();
                }
                catch
                {
                    MyTrans.Rollback();
                }
                finally
                {
                    MyCon.Close();
                    MyCon.Dispose();
                }
            }
        }

        //Send bag to client
        public void UpdateBag()
        {
            try
            {
                string result = "";

                StringWriter stringWriter = new StringWriter();
                XmlTextWriter xmldoc = new XmlTextWriter(stringWriter);

                xmldoc.WriteStartElement("bag");

                string innerXml = "";
                lock (bagPages)
                {
                    foreach (BagPage bp in bagPages)
                        innerXml = innerXml + bp.toXML(MyCharacter);
                }
                xmldoc.WriteRaw(innerXml);

                xmldoc.WriteEndElement();
                xmldoc.Flush();

                xmldoc.Close();

                stringWriter.Flush();

                result = stringWriter.ToString();

                MyCharacter.ClientSocket.socket.BeginSend(result);
            }
            catch { }
        }

        public List<BagPage> getBagLootCopy()
        {
            List<BagPage> result = new List<BagPage>();

            lock (bagPages)
            {
                foreach (BagPage bp in bagPages)
                    result.Add(bp);
            }
            return result;
        }

        public List<Loot> getAllBagItems()
        {
            List<Loot> result = new List<Loot>();

            lock (bagPages)
            {
                foreach (BagPage bp in bagPages)
                {
                    for (int x = 0; x < bp.bagItems.Length; x++)
                    {
                        if (bp.bagItems[x] != null)
                            result.Add(bp.bagItems[x]);
                    }
                }
            }

            return result;
        }

        public Loot getBagItem(int pageNumber, int bagIndex)
        {
            lock (bagPages)
            {
                foreach (BagPage bp in bagPages)
                {
                    if (bp.PageNumber == pageNumber)
                    {
                        if (bp.bagItems.Length > bagIndex)
                            return bp.bagItems[bagIndex];
                        else
                            return null;
                    }
                }
                return null;
            }
        }
        public Loot getBagItem(long ItemGUID)
        {
            lock (bagPages)
            {
                foreach (BagPage bp in bagPages)
                {
                    foreach (Loot loot in bp.bagItems)
                    {
                        if (loot != null && loot.GameUID == ItemGUID)
                            return loot;
                    }
                }
                return null;
            }
        }

        public bool addBagItem(int pageNumber, int bagIndex, Loot loot)
        {
            lock (bagPages)
            {
                foreach (BagPage bp in bagPages)
                {
                    if (bp.PageNumber == pageNumber)
                    {
                        if (bp.bagItems[bagIndex] == null)
                        {
                            bp.bagItems[bagIndex] = loot;
                            return true;
                        }
                        break;
                    }
                }
            }
            return false;
        }
        public bool addBagItem(Loot loot)
        {
            lock (bagPages)
            {
                foreach (BagPage bp in bagPages)
                {
                    for (int x = 0; x < bp.bagItems.Length; x++)
                    {
                        if (bp.bagItems[x] == null)
                        {
                            bp.bagItems[x] = loot;
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        public int totalPages()
        {
            lock (bagPages)
            {
                return bagPages.Count;
            }
        }

        public void createPage()
        {
            BagPage bp = new BagPage();
            lock (bagPages)
            {
                bp.PageNumber = bagPages.Count + 1;
                bagPages.Add(bp);
            }
            UpdateBag();
        }

        public int SlotsAvailable()
        {
            int result = 0;

            lock (bagPages)
            {
                foreach (BagPage bp in bagPages)
                {
                    for (int x = 0; x < bp.bagItems.Length; x++)
                    {
                        if (bp.bagItems[x] == null)
                            result++;
                    }
                }
            }
            return result;
        }

        public Loot removeBagItem(long ItemGUID)
        {
            lock (bagPages)
            {
                foreach (BagPage bp in bagPages)
                {
                    for (int x = 0; x < bp.bagItems.Length; x++)
                    {
                        if (bp.bagItems[x] != null && bp.bagItems[x].GameUID == ItemGUID)
                        {
                            Loot lootToReturn = bp.bagItems[x];
                            bp.bagItems[x] = null;

                            return lootToReturn;
                        }
                    }
                }
            }
            return null;
        }

        public List<Loot> removeAllBagItems()
        {
            List<Loot> result = new List<Loot>();
            lock (bagPages)
            {
                foreach (BagPage bp in bagPages)
                {
                    for (int x = 0; x < bp.bagItems.Length; x++)
                    {
                        if (bp.bagItems[x] != null)
                        {
                            result.Add(bp.bagItems[x]);
                            bp.bagItems[x] = null;
                        }
                    }
                }
            }
            return result;
        }

        //Counts the number of occurances of the item with matching itemID, binding must be bound to me or un-bound (-1)
        public int countItems(int itemId)
        {
            int result = 0;

            lock (bagPages)
            {
                //Scan through all pages
                foreach (BagPage bp in bagPages)
                {
                    //Scan all items
                    for (int x = 0; x < bp.bagItems.Length; x++)
                    {
                        //Find items with matching IDs that are unbound, or bound to me
                        if (bp.bagItems[x] != null &&
                            bp.bagItems[x].ID == itemId &&
                            (bp.bagItems[x].BoundTo == -1 || bp.bagItems[x].BoundTo == MyCharacter.ID))
                        {
                            result++;
                        }
                    }
                }
            }

            return result;
        }
        public bool hasItem(int itemId)
        {
            lock (bagPages)
            {
                foreach (BagPage bp in bagPages)
                {
                    for (int x = 0; x < bp.bagItems.Length; x++)
                    {
                        if (bp.bagItems[x] != null && bp.bagItems[x].ID == itemId)
                            return true;
                    }
                }
            }

            return false;
        }

        public decimal totalWeight()
        {
            decimal result = 0;
            lock (bagPages)
            {
                foreach (BagPage bp in bagPages)
                {
                    for (int x = 0; x < bp.bagItems.Length; x++)
                    {
                        if (bp.bagItems[x] != null)
                            result = result + bp.bagItems[x].Weight;
                    }
                }
            }
            return result;
        }
    }
}
